extends Control

signal lose_game() #定义信号 游戏失败

@onready var player_function_card_hbox = $PlayerFunctionCard/PlayerFunctionCardHbox

@onready var hand_tile_container = $HandTileContainer
@onready var play_tile_detail_container = $PlayTileDetailContainer

@onready var play_panel = $PlayPanel
@onready var play_button = $PlayPanel/PlayButton
@onready var abandon_panel = $AbandonPanel
@onready var abandon_button = $AbandonPanel/AbandonButton

@onready var verify_result_timer = $VerifyResultTimer
@onready var func_card_run_timer = $FuncCardRunTimer

@onready var score_label = $PlayScoreDetail/HBoxContainer/ScoreLabel
@onready var magnification_label = $PlayScoreDetail/HBoxContainer/MagnificationLabel
@onready var get_score = $GetScore

@onready var play_btn_audio = $PlayBtnAudio
@onready var verify_audio = $VerifyAudio
@onready var draw_tile_audio = $DrawTileAudio

@onready var change_money = $ChangeMoney

var tween_rot : Tween
var gameProgress = 1 #1-->回合开始， 2-->单次出牌结算中， 3-->单次出牌结算后， 4-->回合结束
var mahjongVerificationRules = MahjongVerificationRules.new() #牌型验证规则
var currentMahjongDeck #本回合玩家的麻将牌堆
var handTileIdArr #手牌ID
var selectedTileIdArr = [] #选中牌ID

var currentRound #当前回合
var allScoreAdd = 0 #每次出牌分数
var allMagnification = 0 #每次出牌倍率
var finalScore = 0 #每次得分结果
var nocp = PlayerDetail.nocpPlayer #Number of card plays（出牌次数）
var noac = PlayerDetail.noacPlayer #Number of abandoned cards（弃牌次数）

var playSpeed = 1

func _ready() -> void:
	await get_tree().create_timer(1).timeout  # 等待1s
	#0.当前回合
	currentRound = getRoundById() #获取当前round
	getRoundDetail() #更新渲染回合相关
	#1.加载玩家功能牌
	showPlayerFunction(player_function_card_hbox)
	#2.调用玩家功能牌(需等待功能牌计时器)
	await get_tree().create_timer(1).timeout  # 等待3s
	await runFuncCards(player_function_card_hbox.get_children())
	#3.初始化该回合玩家的麻将牌堆
	currentMahjongDeck = PlayerDetail.playerMahjongDeck.duplicate()  # 将玩家牌库赋给当前回合(使用深拷贝)
	currentMahjongDeck.shuffle() # 打乱牌堆，使得每一次进来的排序都不一样
	#4.为玩家抽取14张牌,麻将排序后渲染
	handTileIdArr = drawTiles(14)
	sortTiles(handTileIdArr)
	showHandTile(handTileIdArr)
	draw_tile_audio.play()
	#===4.1更新麻将剩余牌数
	updateRemainingTileNumber()
	#5.将gameProgress更新为2
	gameProgress = 2
	#6.更新出牌/弃牌次数
	updatePlayAndAbandonTimes()


#获取通过id获取当前回合
func getRoundById():
	var roundId = str(RoundDetail.currentBigRound) + "-" + str(RoundDetail.currentSmallRound)
	for item in RoundDetail.rounds:
		if item["roundId"] == roundId:
			return item  # 返回匹配的元素
#获取回合详情
func getRoundDetail():
	$TargetScore.text = str(currentRound.targetScore)
	$ScoreProgressBar.max_value = currentRound.targetScore
	$PlayAndAbandonTimes/CurrentRound.text = currentRound.roundName

#调用玩家功能牌
func runFuncCards(funcCardsObjArr):
	for item in funcCardsObjArr:
		if gameProgress == item.trigger_timing:
			await item.cardFunction()


#加载玩家功能牌
func showPlayerFunction(container):
	for item in PlayerDetail.functionCardCarryArr:
		# 拼接功能牌场景路径
		var scenePath = "res://gameScene/functionCardScene/" + item + "FunctionCard/" + item + "FunctionCard.tscn"
		# 加载场景并确保返回的是一个 PackedScene
		var funcCardScene = load(scenePath)
		# 检查是否是 PackedScene 类型
		if funcCardScene and funcCardScene is PackedScene:  
			# 实例化场景
			var funcCardInstance = funcCardScene.instantiate()
			if funcCardInstance:
				 # 将功能牌添加到 hbox 容器中
				container.add_child(funcCardInstance)
			else:
				print("===未找到该资源===")
		else:
			print("===未找到该资源===")


#为玩家抽牌(返回数组为麻将牌id)
func drawTiles(count: int) -> Array:
	var result = []
	for i in range(count):
		if currentMahjongDeck.size() > 0:
			result.append(currentMahjongDeck.pop_front())
	return result


#渲染玩家手牌
func showHandTile(handTileIdArr):
	clear_container(hand_tile_container)
	sortTiles(handTileIdArr) #排序
	var MAHJONG_SCENE = preload("res://gameScene/mahjongTileScene/mahjongTile.tscn")
	for mahjongId in handTileIdArr:
		var mahjong = MAHJONG_SCENE.instantiate()
		mahjong.mahjong_id = mahjongId
		hand_tile_container.add_child(mahjong)


#麻将排序
func sortTiles(tiles: Array) -> void:
	#使用godot提供的排序方法sort_custom调用自定义compareMahjong方法实现排序具体要求
	tiles.sort_custom(Callable(self, "compareTile"))	


#排序具体规则
func compareTile(a: String, b: String) -> int:
	var typePriority = PlayerDetail.mahjongDeckObject.mahjongPriority
	var typeA = a.split("_")[0]  # 获取牌型
	var typeB = b.split("_")[0]
	var numberA = a.split("_")[1]
	var numberB = b.split("_")[1]
	# 按优先级排序
	if typePriority[typeA] < typePriority[typeB]:
		return true  # a 排在 b 前
	elif typePriority[typeA] > typePriority[typeB]:
		return false  # b 排在 a 前
	else:
		if numberA < numberB:
			return true # a 排在 b 前
		elif numberA > numberB:
			return false # b 排在 a 前
		else:
			return false; # 完全相同 不做改变


#显示出牌/弃牌按钮
func showButton():
	play_panel.visible = true
	abandon_panel.visible = true


#隐藏出牌/弃牌按钮
func hideButton():
	play_panel.visible = false
	abandon_panel.visible = false


#出牌按钮事件
var verifyResult = '' #验证牌型得到的结果
var currentTypeString = "" #用于功能牌获取当前得分牌型
func _on_play_button_pressed() -> void:
	$Speedx2.visible = false
	play_btn_audio.play(0.03)
	#0.对打出的牌进行排序
	sortTiles(selectedTileIdArr)
	
	#1.出牌结算时，隐藏出牌和弃牌按钮，禁止麻将牌交互
	for tile in hand_tile_container.get_children():
		tile.mahjong_btn.disabled = true  # 禁用按钮的交互
	hideButton()
	
	#2.减少出牌次数，更新出牌次数文本
	nocp -= 1
	updatePlayAndAbandonTimes()
	#3.将打出的牌从手牌中移除,并展示在出牌详情区域
	if selectedTileIdArr.size() > 0:
		for tile in hand_tile_container.get_children():
			if tile is Node and tile.mahjong_id:
				if tile.mahjong_id in selectedTileIdArr:
					handTileIdArr.erase(tile.mahjong_id)
					hand_tile_container.remove_child(tile)
					play_tile_detail_container.add_child(tile)
	
	#4.对出牌详情区域的牌进行牌型验证
	await get_tree().create_timer(1).timeout  # 等待1s
	verifyResult = mahjongVerificationRules.verifySelectedTile(selectedTileIdArr)
	if verifyResult.pairDetailObj.pairCount != 0 or verifyResult.pongDetailObj.pongCount != 0 or verifyResult.kanDetailObj.kanCount != 0 or verifyResult.smallShunDetailObj.smallShunCount != 0 or verifyResult.bigShunDetailObj.bigShunCount != 0 or verifyResult.zfbDetailObj.zfbCount != 0 or verifyResult.fengDetailObj.fengCount != 0:
		await updateScoreByVerifyResult(verifyResult)
	#===4.1出牌验证结算后，将gameProgress改为3，调用功能牌后，改为2
	gameProgress = 3
	if verifyResult.pairDetailObj.pairCount != 0 or verifyResult.pongDetailObj.pongCount != 0 or verifyResult.kanDetailObj.kanCount != 0 or verifyResult.smallShunDetailObj.smallShunCount != 0 or verifyResult.bigShunDetailObj.bigShunCount != 0 or verifyResult.zfbDetailObj.zfbCount != 0 or verifyResult.fengDetailObj.fengCount != 0:
		await runFuncCards(player_function_card_hbox.get_children())
	gameProgress = 2
	
	#5.更新finalScore分数,将allScoreAdd，allMagnification 归0
	if allScoreAdd * allMagnification > 0:
		await get_tree().create_timer(1).timeout  # 等待1s
		finalScore += (allScoreAdd * allMagnification)
		get_score.text = str(finalScore)
		await get_tree().create_timer(0.5).timeout  # 等待0.5s
		if allScoreAdd * allMagnification > 0:
			$ScoreProgressBarAudio.play()
			tween_rot = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK).set_parallel(false)
			tween_rot.tween_property($ScoreProgressBar,"value",finalScore,1)
	allScoreAdd = 0
	score_label.text = str(allScoreAdd)
	allMagnification = 0
	magnification_label.text = str(allMagnification)
	await get_tree().create_timer(0.5).timeout  # 等待0.5秒
	#6.恢复操作
	stopFire()
	selectedTileIdArr = []
	verifyResult = ''
	verify_result_timer.wait_time = 1 / playSpeed #验证计时器归1
	func_card_run_timer.wait_time = 1 / playSpeed #功能牌计时器归1
	labelRunTime = 1 / playSpeed#Label动画运行时间
	print("labelRunTime=",labelRunTime)
		
	#7.清空出牌区域
	clear_container(play_tile_detail_container)
	
	#8.判断分数是否达标
	#分数达标
	if finalScore >= currentRound.targetScore:
		#播放粒子
		$SuccessParticles1.emitting = true
		$SuccessParticles2.emitting = true
		$SuccessParticles3.emitting = true
		#8.1将gameProgress改为4,手牌麻将禁止交互
		gameProgress = 4
		for tile in hand_tile_container.get_children():
			tile.mahjong_btn.disabled = true  # 禁用按钮的交互
		hideButton()
		#8.2调用功能牌
		await runFuncCards(player_function_card_hbox.get_children())
		#8.3开始结算金币
		await get_tree().create_timer(1).timeout  # 等待1秒
		$ChangeMoney.visible = true
		await get_tree().create_timer(1).timeout  # 等待1秒
		$ChangeMoney.changeMoney()
		#8.4更新回合
		RoundDetail.currentSmallRound += 1
		# 如果小回合大于 5，增加大回合并重置小回合
		if RoundDetail.currentSmallRound > 5:
			RoundDetail.currentBigRound += 1
			RoundDetail.currentSmallRound = 1  # 重置小回合为 1
		#9.直接返回
		return
	#分数未达标
	else:
		if nocp == 0:
			$LoseLabel.visible = true
			#手牌麻将禁止交互
			for tile in hand_tile_container.get_children():
				tile.mahjong_btn.disabled = true  # 禁用按钮的交互
			hideButton()
			await get_tree().create_timer(1).timeout  # 等待1秒
			emit_signal("lose_game") # 发送信号 整个游戏失败
	#9.补充手牌
	await get_tree().create_timer(0.5).timeout  # 等待0.5s
	play_btn_audio.play(0.03)
	updateHand()
	#===9.1更新麻将剩余牌数
	updateRemainingTileNumber()
	#10.验证是否胡牌
	var convertHandTileIdArr = mahjongVerificationRules.convert_card_id(handTileIdArr)
	var isHuFlag = mahjongVerificationRules.can_hu(convertHandTileIdArr,0)
	#===10.1胡牌后的操作
	if isHuFlag:
		print("isHuFlag=",isHuFlag)
	
	#11.展示2倍速按钮
	$Speedx2.visible = true
	


#弃牌按钮事件
func _on_abandon_button_pressed() -> void:
	play_btn_audio.play(0.03)
	#1.出牌结算时，隐藏出牌和弃牌按钮,禁止麻将牌交互
	for tile in hand_tile_container.get_children():
		tile.mahjong_btn.disabled = true  # 禁用按钮的交互
	hideButton()
	
	#2.减少弃牌次数，更新弃牌次数文本
	noac -= 1
	updatePlayAndAbandonTimes()
	if noac == 0:
		abandon_button.disabled = true
		abandon_button.visible = false
	
	#3.将弃出的牌从手牌中移除,并展示在出牌详情区域
	if selectedTileIdArr.size() > 0:
		for tile in hand_tile_container.get_children():
			if tile is Node and tile.mahjong_id:
				if tile.mahjong_id in selectedTileIdArr:
					handTileIdArr.erase(tile.mahjong_id)
					hand_tile_container.remove_child(tile)
					play_tile_detail_container.add_child(tile)
	
	#4.特殊功能牌调用
		
	#5.清除出牌区域，补全手牌，更新牌堆数目
	await get_tree().create_timer(1).timeout  # 等待1s
	clear_container(play_tile_detail_container) # 清除出牌展示区域
	updateHand()  # 更新手牌
	#===5.1更新麻将剩余牌数
	updateRemainingTileNumber()
		
	#6.弃牌后，验证手牌是否胡牌
	var convertHandTileIdArr = mahjongVerificationRules.convert_card_id(handTileIdArr)
	var isHuFlag = mahjongVerificationRules.can_hu(convertHandTileIdArr,0)
	#===6.1胡牌后的操作
	if isHuFlag:
		print("isHuFlag=",isHuFlag)
	
	#7.清空 selectedMahjongs 数组
	if selectedTileIdArr.size() > 0:
		selectedTileIdArr.clear()  # 清空已选择的牌
	else:
		print("没有选择牌！")



#根据验证结果更新分数
func updateScoreByVerifyResult(verifyResult):
	#1.对子详情
	#1.1得分牌突出显示,label特效展示，更新PlayScoreDetai
	await startCheck(verifyResult.pairDetailObj.pairCount,verifyResult.pairDetailObj.pairDetailArr,"对子","pair")
	
	#2.碰子详情
	#2.1得分牌突出显示,label特效展示，更新PlayScoreDetai
	await startCheck(verifyResult.pongDetailObj.pongCount,verifyResult.pongDetailObj.pongDetailArr,"碰子","pong")
	
	#3.杠子详情
	#3.1得分牌突出显示,label特效展示，更新PlayScoreDetai
	await startCheck(verifyResult.kanDetailObj.kanCount,verifyResult.kanDetailObj.kanDetailArr,"杠子","kan")
	
	#4.小顺详情
	#4.1得分牌突出显示,label特效展示，更新PlayScoreDetai
	await startCheck(verifyResult.smallShunDetailObj.smallShunCount,verifyResult.smallShunDetailObj.smallShunDetailArr,"小顺子","smallShun")
	
	#5.大顺详情
	#5.1得分牌突出显示,label特效展示，更新PlayScoreDetai
	await startCheck(verifyResult.bigShunDetailObj.bigShunCount,verifyResult.bigShunDetailObj.bigShunDetailArr,"大顺子","bigShun")
	
	#6.中发白详情
	#6.1得分牌突出显示,label特效展示，更新PlayScoreDetai
	await startCheck(verifyResult.zfbDetailObj.zfbCount,verifyResult.zfbDetailObj.zfbDetailArr,"中发白","zfb")
	
	#7.风详情
	#7.1得分牌突出显示,label特效展示，更新PlayScoreDetai
	await startCheck(verifyResult.fengDetailObj.fengCount,verifyResult.fengDetailObj.fengDetailArr,"大旋风","feng")


#得分牌突出显示，label特效展示，更新PlayScoreDetai
func startCheck(count,detailArr,type,typeString):
	if count > 0:
		for i in detailArr:
			#1.播放音效
			verify_audio.play() #播放音效
			
			#2.随着循环逐渐加快节奏
			verify_result_timer.wait_time = verify_result_timer.wait_time * 0.96
			func_card_run_timer.wait_time = func_card_run_timer.wait_time * 0.96
			
			#3.启动计时器
			verify_result_timer.start()
			
			#4.添加一些显示特效
			#====特效添加区==start
			#===4.1随机label展示
			# 获取随机选择的 Label 节点
			$PlayDetailLabel.text = type
			labelEffectsStart($PlayDetailLabel)
			#===4.2得分麻将改色
			for j in play_tile_detail_container.get_children():
				if i.has(j.mahjong_id):
					j.modulate = Color(0.5, 0.8, 0.5)
			#====特效添加区==end
			
			#5.更新PlayScoreDetail
			updatePlayScoreDetail(typeString)
			
			#6.计时结束，做恢复操作
			await verify_result_timer.timeout
			#===6.1恢复并隐藏Label节点
			labelEffectsEnd($PlayDetailLabel)
			#===6.2将得分麻将恢复颜色
			for j in play_tile_detail_container.get_children():
				if i.has(j.mahjong_id):
					j.modulate = Color(1, 1, 1)
			
			#7.调用功能牌
			currentTypeString = typeString #用于功能牌获取当前得分牌型
			await runFuncCards(player_function_card_hbox.get_children())
			currentTypeString = "" #置空


#开启Label特效
var labelRunTime = 1
func labelEffectsStart(label):
	var x = randi() % 1000
	var y = randi() % 600
	label.position = Vector2(x , y)
	label.visible = true
	tween_rot = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK).set_parallel(false)
	labelRunTime = labelRunTime * 0.96
	tween_rot.tween_property(label,"scale",Vector2(3,3),labelRunTime)
	label.scale = Vector2(1,1)
#关闭Label特效
func labelEffectsEnd(label):
	label.visible = false


#更新PlayScoreDetail
func updatePlayScoreDetail(typeString):
	var score = PlayerDetail.scoreMapping[typeString]
	allScoreAdd += score
	score_label.text = str(allScoreAdd)
	var magnification = PlayerDetail.magnificationMapping[typeString]
	allMagnification += magnification
	magnification_label.text = str(allMagnification)
	if allScoreAdd >= 200:
		playScoreFire()
	if allMagnification >= 20:
		playMagnificationFire()


#补充手牌
func updateHand():
	var handSize = hand_tile_container.get_child_count()
	if handSize < 14:
		var supplementaryHand = drawTiles(14 - handSize)
		handTileIdArr.append_array(supplementaryHand)
		showHandTile(handTileIdArr)

#播放/停止火特效
func playScoreFire():
	$ScoreFire.emitting = true
	$ScoreFire/RedFire.emitting = true
func playMagnificationFire():
	$MagnificationFire.emitting = true
	$MagnificationFire/RedFire.emitting = true
func stopFire():
	$ScoreFire.emitting = false
	$ScoreFire/RedFire.emitting = false
	$MagnificationFire.emitting = false
	$MagnificationFire/RedFire.emitting = false

#更新出牌/弃牌次数
func updatePlayAndAbandonTimes():
	$PlayAndAbandonTimes/PlayTimesLabel.text = "出" + "\n" + str(nocp)
	$PlayAndAbandonTimes/AbandonTimesLabel.text = "弃" + "\n" + str(noac)

#更新剩余牌数
func updateRemainingTileNumber():
	$RemainingTileNumber.text = "剩余牌数：" + str(currentMahjongDeck.size())

#清空容器
func clear_container(container: Node):
	for c in container.get_children():
		container.remove_child(c)
		c.queue_free()

#切换2倍速
func _on_speedx_2_toggled(toggled_on: bool) -> void:
	if toggled_on == true:
		playSpeed = 3.0
		verify_result_timer.wait_time = 1 / playSpeed
		func_card_run_timer.wait_time = 1 / playSpeed
		labelRunTime = 1 / playSpeed#Label动画运行时间
	else:
		playSpeed = 1.0
		verify_result_timer.wait_time = 1 / playSpeed
		func_card_run_timer.wait_time = 1 / playSpeed
		labelRunTime = 1 / playSpeed#Label动画运行时间
		
